package com.syg.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * RouteDefinition 提供 text 字符串创建对象（yaml配置中属性值），格式为：
 *       ${id}=${uri},${predicates[0]},${predicates[1]}...${predicates[n]}  ,构造函数为public RouteDefinition(String text) ;
 *
 * 格式 ${name}=${args[0]},${args[1]}...${args[n]}  构造函数为:public PredicateDefinition(String text);
 * ${name}=${args[0]},${args[1]}...${args[n]}   构造函数为public FilterDefinition(String text);
 *
 * @return
 */
@Slf4j
@Service
public class MySqlRouteService {

    public Mono<Void> save(Mono<RouteDefinition> route) {
        return Mono.empty();
    }


    public Mono<Void> delete(Mono<String> routeId) {
        return Mono.empty();
    }

    /**
     * 获取路由定义信息
     * @return
     */
    public List<RouteDefinition> getRouteDefinitions() {
        Map<String, RouteDefinition> routeDefinitionMaps = this.loadRouteDefinition();
        if(CollectionUtils.isEmpty(routeDefinitionMaps)){
            return null;
        }

        Collection<RouteDefinition> collections = routeDefinitionMaps.values();
        return new ArrayList<>(collections);

    }

    /**
     * RouteDefinition 提供 text 字符串创建对象（yaml配置中属性值），格式为：
     *       ${id}=${uri},${predicates[0]},${predicates[1]}...${predicates[n]}  ,构造函数为public RouteDefinition(String text) ;
     *
     * 格式 ${name}=${args[0]},${args[1]}...${args[n]}  构造函数为:public PredicateDefinition(String text);
     * ${name}=${args[0]},${args[1]}...${args[n]}   构造函数为public FilterDefinition(String text);
     *
     * @return
     */
    private Map<String, RouteDefinition> loadRouteDefinition() {
        // 来自于DB
        Map<String, String> map = new HashMap<>();

        // 测试数据开始
        Map<String, String> predicateStr = new HashMap<>();
        predicateStr.put("pattern", "/application01/**");
        PredicateDefinition predicate = new PredicateDefinition();
        // 谓语定义名字，通过 name 对应到 org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory 的实现类
        predicate.setName("Path");
        predicate.setArgs(predicateStr);
        RouteDefinition routeDef = new RouteDefinition();
        routeDef.setId("application01");

        Map<String, String> filterDefinitionStr = new HashMap<>();
        // 过滤器定义key。通过 name 对应到 org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory 的实现类
        // RewritePath  这个的用法存疑
        filterDefinitionStr.put("parts", "1");
        // filterDefinitionStr.put("RewritePath", "http://localhost:8081/testGateway1");
        FilterDefinition filterDefinition = new FilterDefinition();
        // 过滤器定义名字。通过 name 对应到 org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory 的实现类
        filterDefinition.setName("StripPrefix");
        filterDefinition.setArgs(filterDefinitionStr);


        try {
            routeDef.setUri(new URI("http://localhost:8081"));
            ArrayList<PredicateDefinition> listPredicate = new ArrayList<>();
            listPredicate.add(predicate);

            ArrayList<FilterDefinition> listFilterDefinition = new ArrayList<>();
            listFilterDefinition.add(filterDefinition);

            routeDef.setPredicates(listPredicate);
            routeDef.setFilters(listFilterDefinition);
            map.put("application01", new ObjectMapper().writeValueAsString(routeDef));
            if (CollectionUtils.isEmpty(map)) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 测试数据结束


        Map<String, RouteDefinition> routeDefinitionMaps = new HashMap<>();
        List<String> gatewayRoutes = new ArrayList<>(map.values());

        gatewayRoutes.forEach(value->{
            try {
                RouteDefinition routeDefinition = new ObjectMapper().readValue(value, RouteDefinition.class);
                if(routeDefinition!=null && routeDefinition.getFilters()==null) {
                    routeDefinition.setFilters(new ArrayList<>());
                }
                if(routeDefinition!=null && routeDefinition.getPredicates()==null) {
                    routeDefinition.setPredicates(new ArrayList<>());
                }
                routeDefinitionMaps.put(routeDefinition.getId(), routeDefinition);
            } catch (JsonProcessingException e) {
                log.error("json route info error",e);
            }
        });
        return routeDefinitionMaps;
    }
}
